import sys,re
from collections import OrderedDict

class DBC(object):
    def __init__(self, name, self_node, gen_all,Faceto_node):
        self.name = name
        self.self_node = self_node
        self.gen_all = gen_all
        self.FaceTo_node = Faceto_node

        # Dictionary of messages with the MSG-ID as the key
        self.messages = OrderedDict()
        self.nodes = []

class Message(object):
    def __init__(self, mid, name, dlc, sender):
        self.mid = mid
        self.name = name
        self.dlc = dlc
        self.sender = sender
        self.signals = OrderedDict()
        self.Cycle = "XXX"
        self.CheckSum = False   #if message has checksum signal then set true and generate checksum code
    # Adds the signal to the dictionary of signals of this message
    def add_signal(self, s):
        self.signals[s.Name] = s

    def Get_CycleTime(self,time):
        self.Cycle = time

    def Bounds_Judge(self,Msg_id,Msg_length,Msg_id_Array):
        if(int(Msg_id) < 0):
                raise ValueError('#error' + Msg_id + 'is out of bounds')
            
        if Msg_id  not in Msg_id_Array:
            Msg_id = Msg_id_Array.append(Msg_id)
        else:
            raise ValueError('#error' + Msg_id + 'is already been used')

        #if int(Msg_length) > 8 or int(Msg_length) < 1:
            #raise ValueError('#error' + Msg_id + ' has an incorrect number of bytes. It must be between 1 and 8 bytes')

class Signal(object):
    def __init__(self,Name,StartBit,BitSize,ByteOrder_ValueType,Factor,Offset,Min_Value,Max_Value,Unit,Receiver,Signal_Min,Signal_Max):
        self.Name = Name
        self.StartBit = int(StartBit)
        self.BitSize = int(BitSize)
        self.ByteOrder_ValueType = ByteOrder_ValueType
        self.Factor = float(Factor)
        self.Offset = float(Offset)
        self.Factor_str = Factor
        self.Offset_str = Offset
        self.Min_Value = float(Min_Value)
        self.Max_Value = float(Max_Value)
        self.Min_Value_str = Min_Value
        self.Max_Value_str = Max_Value
        self.Unit = Unit
        self.Receiver = Receiver
        self.Signal_Min = Signal_Min
        self.Signal_Max = Signal_Max

        self.EnumInfo = {}

        self.Code_Type = "u"
        if self.is_signed():
            self.Code_Type = "s"
        if self.BitSize <= 8 :
            self.Code_Type += 'int8'
        elif self.BitSize <= 16 :
            self.Code_Type += 'int16'
        elif self.BitSize <= 32 :
            self.Code_Type += 'int32'
        else:
            self.Code_Type += 'int64'


    # Returns true if the signal is defined in the DBC as a signed type
    def is_signed(self):
        return '-' == self.ByteOrder_ValueType[1]

    # Returns true if the signal is defined in the DBC as a intel type
    def is_MOTOROLA(self):
         return "0" == self.ByteOrder_ValueType[0]

    # Returns the variable type (float, int, or enum) based ont he signal data range
    def Get_Signal_Var_Type(self):
        if self.Factor_str.count(".00000") >= 1:
            return "real64_T"
        elif '.' in self.Factor_str or 'e-' in self.Factor_str or 'E-' in self.Factor_str:
            return "real32_T"
        elif '.' in self.Offset_str or 'e-' in self.Offset_str or 'E-' in self.Offset_str:
            return "real32_T"
        else:
            physical_max = (2**self.BitSize) * self.Factor + self.Offset
            if '-' == self.ByteOrder_ValueType[1]:
                physical_max *= 2
            ret = "uint32_T"
            if physical_max == 2:
                ret = "boolean_T"
            elif physical_max <= 256:
                ret = "uint8_T"
            elif physical_max <= 65536:
                ret = "uint16_T"
            # If the signal is signed, or the offset is negative, remove "u" to use "int" type.
            if self.is_signed() or self.Offset < 0:
                ret = ret[1:]
            return ret
